import { useRequest } from 'ahooks'

import {
  Button,
  Checkbox,
  Col,
  Descriptions,
  Form,
  Icon,
  Input,
  Modal,
  Radio,
  Row,
  Spin,
  Tabs,
  Tooltip,
  Typography,
  message,
} from 'antd'
import React, { useRef, useState } from 'react'
import { VersionStateMap } from '../ProcessVersion/VersionPageTable'
import request from '@/utils/request'
import CodeEditor from '@/components/CodeEditor'
import DynamicHttpHeaders, {
  clipboardTextHeaderValues,
  toMap,
} from '@/components/DynamicHttpHeaders'
import DynamicKeyValuePairs from '@/components/DynamicKeyValuePairs'
import { SmallFormLayout } from '@/layouts/Form'
import Space from '@/components/Space'
import ComboGrid from '@/pages/Transformer/components/ComboGrid'

const { Item } = Descriptions
const { TabPane } = Tabs
const { Text } = Typography

export const mapFormatToEditorMode = {
  JSON: 'json',
  XML: 'xml',
  NONE: 'text',
}

function loadInitContent({ versionId }) {
  return request.get(`/process/getInitContent?versionId=${versionId}`)
}

function ProcessRun({
  data,
  title,
  onCancel,
  visible,
  initContentLoader = loadInitContent,
  processLogId,
  shardingKey,
}) {
  const reRun = title === '流程重演'
  const { processId, versionId } = data
  const [dynamicVersionId, setDynamicVersionId] = useState(versionId)
  const [requestBodyFormat, setRequestBodyFormat] = useState('JSON')
  const [instanceId, setInstanceId] = useState()
  const [processVariables, setProcessVariables] = useState({})
  const [httpHeaders, setHttpHeaders] = useState([])
  const responseRef = useRef()
  const requestEditorRef = useRef(null)
  const headersRef = useRef(null)

  const [updateStatusWhenRetrySuccess, setUpdateStatusWhenRetrySuccess] = useState(!!processLogId)

  const { data: process = {}, loading } = useRequest(
    () => {
      if (!processId)
        return Promise.resolve({})

      return request.get(`/process/getProcess?processId=${processId}`)
    },
    {
      refreshDeps: [processId],
    },
  )

  const { loading: loading2 } = useRequest(
    () => {
      if (!versionId)
        return Promise.resolve({})

      return initContentLoader({ versionId }).then(data => data || loadInitContent({ versionId }))
    },
    {
      refreshDeps: [versionId],
      onSuccess(data) {
        if (data) {
          const editor = requestEditorRef.current
          editor.setMode(data.format)
          editor.setValue(data.content)
          setHttpHeaders(data.httpHeaders || [])
          setProcessVariables(data.variables)
          setInstanceId(data.instanceId)
          setRequestBodyFormat(data.format)
        }
      },
    },
  )

  const { loading: okButtonLoading, run } = useRequest(
    () =>
      request.post('/process/run', {
        data: {
          processId,
          versionId: dynamicVersionId,
          instanceId,
          payload: requestEditorRef.current.getValue(),
          format: requestBodyFormat,
          variables: processVariables,
          httpHeaders: toMap(httpHeaders),
          updateStatusWhenRetrySuccess,
          processLogId,
          shardingKey,
          reRun,
        },
      }),
    {
      manual: true,
      onSuccess(data) {
        if (data) {
          const editor = responseRef.current
          editor.setMode(mapFormatToEditorMode[data.responseBodyFormat])
          editor.setValue(data.responseBody)
        }
      },
    },
  )

  return (
    <Modal
      width={1000}
      title={title}
      onCancel={onCancel}
      visible={visible}
      destroyOnClose
      footer={
        <Row type="flex" justify="space-between" align="middle">
          {processLogId
            ? (
            <Space style={{ display: 'flex', alignItems: 'center' }}>
              <Checkbox
                checked={updateStatusWhenRetrySuccess}
                onChange={e => setUpdateStatusWhenRetrySuccess(e.target.checked)}
              />
              <span>重演成功时，更新日志状态</span>
              <Tooltip title="如果重演成功，则将当前日志的状态更新为「重演成功」">
                <Icon style={{ opacity: '.5', cursor: 'help' }} type="question-circle-o" />
              </Tooltip>
            </Space>
              )
            : (
            <div />
              )}

          <div>
            {reRun && <span className="mr">
              重演版本号<Tooltip title="基于某个版本的流程进行重演，默认为流程在执行时所使用的版本号">
                <Icon style={{ opacity: '.5', cursor: 'help', marginLeft: 3, marginRight: 2 }} type="question-circle-o" />
              </Tooltip>：
              <ComboGrid
                  style={{ width: 75 }}
                  url={`/process/listVersions?processId=${processId}`}
                  method="get"
                  popupStyle={{ width: 400 }}
                  placeholder="--请选择--"
                  search={false}
                  destroyPopupOnHide
                  label="versionNumber"
                  rowKey="versionId"
                  pick="radio"
                  value={[{ versionId: dynamicVersionId }]}
                  onChange={v => setDynamicVersionId(v[0].versionId)}
                  columns={[
                    {
                      title: '版本号',
                      dataIndex: 'versionNumber',
                    },
                    {
                      title: '版本状态',
                      dataIndex: 'versionState',
                      render: text => VersionStateMap[text],
                    },
                    {
                      title: '创建时间',
                      dataIndex: 'createDate',
                    },
                  ]}
                  slickTableProps={{ allowClear: false }}
              />
            </span>
            }
            <Button type="default" onClick={onCancel}>
              取消
            </Button>
            <Button type="primary" onClick={run} loading={okButtonLoading}>
              运行
            </Button>
          </div>
        </Row>
      }
    >
      <Spin spinning={loading || loading2}>
        <Descriptions column={4}>
          <Item label="流程名称">{process.processName}</Item>
          <Item label="流程编码">{process.processCode}</Item>
        </Descriptions>
        <Row gutter={16}>
          <Col span={12}>
            <Tabs defaultActiveKey="message">
              <TabPane tab="消息" key="message">
                <Row type="flex" align="middle" style={{ height: 24 }}>
                  <Text>请求报文：</Text>
                  <Radio.Group
                    value={requestBodyFormat}
                    buttonStyle="solid"
                    onChange={e => setRequestBodyFormat(e.target.value)}
                  >
                    <Radio key="JSON" value="JSON">
                      JSON
                    </Radio>
                    <Radio key="XML" value="XML">
                      XML
                    </Radio>
                    <Radio key="NONE" value="NONE">
                      普通文本
                    </Radio>
                  </Radio.Group>
                </Row>
                <CodeEditor
                  ref={requestEditorRef}
                  mode={mapFormatToEditorMode[requestBodyFormat]}
                  height={481}
                  style={{ marginTop: 8 }}
                />
              </TabPane>
              <TabPane tab="实例数据" key="instanceData">
                <Form {...SmallFormLayout}>
                  <Form.Item label="实例ID">
                    <Input
                      value={instanceId}
                      onChange={e => setInstanceId(e.target.value)}
                      placeholder="请输入"
                    />
                  </Form.Item>
                </Form>
              </TabPane>
              <TabPane tab="HTTP请求头" key="httpHeaders">
                <DynamicHttpHeaders
                  ref={headersRef}
                  value={httpHeaders}
                  onChange={setHttpHeaders}
                />
                <Button
                  onClick={async () => {
                    try {
                      const headers = await clipboardTextHeaderValues()
                      headersRef.current.resetList(headers)
                    }
                    catch (error) {
                      message.error(error.message)
                    }
                  }}
                  className="margin-top"
                  icon="bg-colors"
                  ghost
                  type="primary"
                >
                  填充Header
                </Button>
              </TabPane>
              <TabPane tab="流程变量" key="variables">
                <DynamicKeyValuePairs value={processVariables} onChange={setProcessVariables} />
              </TabPane>
            </Tabs>
          </Col>
          <Col span={12} style={{ marginTop: 35 + 15 }}>
            <Row type="flex" align="middle" style={{ height: 24 }}>
              <Text>响应报文</Text>
            </Row>
            <CodeEditor ref={responseRef} readOnly height={481} style={{ marginTop: 8 }} />
          </Col>
        </Row>
      </Spin>
    </Modal>
  )
}

export default ProcessRun
